package com.autoglm.android.core.execution

import android.content.Context
import android.content.Intent
import android.net.Uri
import android.provider.Settings
import android.util.Log
import com.autoglm.android.core.db.AppKnowledgeBase
import com.autoglm.android.core.models.ErrorType
import com.autoglm.android.core.models.RecoveryActionType
import com.autoglm.android.core.models.RecoveryResult
import com.autoglm.android.core.models.RecoveryStrategy
import com.autoglm.android.core.models.TaskExecutionPlan
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.withContext

/**
 * 恢复管理器，负责处理任务执行中的错误并尝试恢复
 */
class RecoveryManager(
    private val context: Context,
    private val taskStateManager: TaskStateManager,
    private val appKnowledgeBase: AppKnowledgeBase
) {
    companion object {
        private const val TAG = "RecoveryManager"
        private const val MAX_RECOVERY_ATTEMPTS = 3
    }
    
    // 当前恢复尝试计数
    private val recoveryAttemptCounter = mutableMapOf<String, Int>()
    
    /**
     * 尝试恢复执行
     * 
     * @param plan 任务执行计划
     * @param currentStepId 当前步骤ID
     * @param errorType 错误类型
     * @param errorMessage 错误消息
     * @return 恢复结果
     */
    suspend fun attemptRecovery(
        plan: TaskExecutionPlan,
        currentStepId: String,
        errorType: ErrorType,
        errorMessage: String?
    ): RecoveryResult = withContext(Dispatchers.Default) {
        Log.d(TAG, "Attempting recovery for step $currentStepId, error: $errorType, message: $errorMessage")
        
        // 获取当前步骤
        val currentStep = plan.steps.find { it.id == currentStepId }
            ?: return@withContext RecoveryResult.failure("找不到步骤ID: $currentStepId")
        
        // 获取应用包名
        val packageName = plan.targetApp?.packageName
            ?: return@withContext RecoveryResult.failure("找不到目标应用信息")
        
        // 检查恢复尝试次数
        val attemptKey = "$currentStepId:$errorType"
        val attempts = recoveryAttemptCounter.getOrDefault(attemptKey, 0) + 1
        recoveryAttemptCounter[attemptKey] = attempts
        
        if (attempts > MAX_RECOVERY_ATTEMPTS) {
            Log.w(TAG, "Exceeded maximum recovery attempts for $attemptKey")
            return@withContext RecoveryResult.failure("超过最大恢复尝试次数: $MAX_RECOVERY_ATTEMPTS")
        }
        
        // 获取恢复策略
        val strategy = determineRecoveryStrategy(plan, currentStep, errorType, attempts)
        
        // 执行恢复策略
        when (strategy.actionType) {
            RecoveryActionType.RETRY_OPERATION -> {
                // 简单重试当前步骤
                Log.d(TAG, "Recovery strategy: Retry operation")
                return@withContext RecoveryResult.success(currentStepId)
            }
            
            RecoveryActionType.WAIT_AND_RETRY -> {
                // 等待后重试
                Log.d(TAG, "Recovery strategy: Wait ${strategy.waitTimeMs}ms and retry")
                delay(strategy.waitTimeMs)
                return@withContext RecoveryResult.success(currentStepId)
            }
            
            RecoveryActionType.TRY_ALTERNATIVE_PATH -> {
                // 尝试替代路径
                Log.d(TAG, "Recovery strategy: Try alternative path")
                val alternativeStepId = strategy.alternativePath?.firstOrNull()
                    ?: return@withContext RecoveryResult.failure("策略指定替代路径，但路径为空")
                    
                return@withContext RecoveryResult.success(alternativeStepId)
            }
            
            RecoveryActionType.RESTART_APP -> {
                // 重启应用
                Log.d(TAG, "Recovery strategy: Restart app")
                val result = restartApp(packageName)
                return@withContext if (result) {
                    // 找到应用入口步骤
                    val entryStepId = findAppEntryStep(plan)
                        ?: return@withContext RecoveryResult.failure("无法找到应用入口步骤")
                        
                    RecoveryResult.success(entryStepId)
                } else {
                    RecoveryResult.failure("重启应用失败")
                }
            }
            
            RecoveryActionType.CLEAR_APP_DATA -> {
                // 请求用户清除应用数据
                Log.d(TAG, "Recovery strategy: Request clear app data")
                // 这需要用户交互，打开应用信息界面
                openAppSettings(packageName)
                return@withContext RecoveryResult.failure("需要用户清除应用数据")
            }
            
            RecoveryActionType.REQUEST_USER_HELP -> {
                // 请求用户帮助
                Log.d(TAG, "Recovery strategy: Request user help")
                return@withContext RecoveryResult.failure("需要用户介入解决问题: ${errorMessage ?: "未知错误"}")
            }
            
            RecoveryActionType.SKIP_STEP -> {
                // 跳过当前步骤
                Log.d(TAG, "Recovery strategy: Skip step")
                val nextStepIndex = plan.steps.indexOfFirst { it.id == currentStepId } + 1
                
                if (nextStepIndex < plan.steps.size) {
                    return@withContext RecoveryResult.success(plan.steps[nextStepIndex].id)
                } else {
                    return@withContext RecoveryResult.failure("已是最后一步，无法跳过")
                }
            }
            
            RecoveryActionType.ABORT_TASK -> {
                // 中止任务
                Log.d(TAG, "Recovery strategy: Abort task")
                return@withContext RecoveryResult.failure("任务中止: ${strategy.description ?: errorMessage ?: "未知错误"}")
            }
        }
    }
    
    /**
     * 确定恢复策略
     */
    private suspend fun determineRecoveryStrategy(
        plan: TaskExecutionPlan,
        currentStep: ExecutionStep,
        errorType: ErrorType,
        attemptCount: Int
    ): RecoveryStrategy {
        // 首先检查步骤中定义的恢复策略
        currentStep.recoveryStrategies?.forEach { strategy ->
            if (strategy.errorType == errorType) {
                return strategy
            }
        }
        
        // 如果步骤没有定义恢复策略，使用默认策略
        return when (errorType) {
            ErrorType.ELEMENT_NOT_FOUND -> {
                if (attemptCount <= 2) {
                    // 元素可能需要时间加载，等待后重试
                    RecoveryStrategy(
                        errorType = errorType,
                        actionType = RecoveryActionType.WAIT_AND_RETRY,
                        waitTimeMs = 2000,
                        description = "等待界面元素加载"
                    )
                } else {
                    // 多次尝试后仍找不到元素，可能在错误的界面
                    RecoveryStrategy(
                        errorType = errorType,
                        actionType = RecoveryActionType.REQUEST_USER_HELP,
                        description = "无法找到界面元素，可能应用界面已更改"
                    )
                }
            }
            
            ErrorType.OPERATION_TIMEOUT -> {
                RecoveryStrategy(
                    errorType = errorType,
                    actionType = RecoveryActionType.RETRY_OPERATION,
                    description = "操作超时，重试"
                )
            }
            
            ErrorType.APP_NOT_RESPONDING -> {
                RecoveryStrategy(
                    errorType = errorType,
                    actionType = RecoveryActionType.RESTART_APP,
                    description = "应用无响应，重启应用"
                )
            }
            
            ErrorType.PERMISSION_DENIED -> {
                RecoveryStrategy(
                    errorType = errorType,
                    actionType = RecoveryActionType.REQUEST_USER_HELP,
                    description = "需要授予权限"
                )
            }
            
            ErrorType.APP_NOT_INSTALLED -> {
                RecoveryStrategy(
                    errorType = errorType,
                    actionType = RecoveryActionType.ABORT_TASK,
                    description = "应用未安装"
                )
            }
            
            ErrorType.UNEXPECTED_SCREEN -> {
                if (attemptCount == 1) {
                    // 首次遇到意外屏幕，尝试返回
                    RecoveryStrategy(
                        errorType = errorType,
                        actionType = RecoveryActionType.TRY_ALTERNATIVE_PATH,
                        alternativePath = listOf("back_action"),
                        description = "遇到意外屏幕，尝试返回"
                    )
                } else {
                    // 多次尝试后仍在意外屏幕，重启应用
                    RecoveryStrategy(
                        errorType = errorType,
                        actionType = RecoveryActionType.RESTART_APP,
                        description = "多次遇到意外屏幕，重启应用"
                    )
                }
            }
            
            ErrorType.CONNECTION_ERROR -> {
                RecoveryStrategy(
                    errorType = errorType,
                    actionType = RecoveryActionType.WAIT_AND_RETRY,
                    waitTimeMs = 5000,
                    description = "网络连接错误，等待后重试"
                )
            }
            
            ErrorType.UNKNOWN -> {
                if (attemptCount <= 1) {
                    RecoveryStrategy(
                        errorType = errorType,
                        actionType = RecoveryActionType.RETRY_OPERATION,
                        description = "未知错误，重试"
                    )
                } else {
                    RecoveryStrategy(
                        errorType = errorType,
                        actionType = RecoveryActionType.REQUEST_USER_HELP,
                        description = "多次出现未知错误，需要用户介入"
                    )
                }
            }
        }
    }
    
    /**
     * 重启应用
     */
    private suspend fun restartApp(packageName: String): Boolean = withContext(Dispatchers.Main) {
        try {
            // 强制停止应用
            val forceStopIntent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
            forceStopIntent.data = Uri.parse("package:$packageName")
            forceStopIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            context.startActivity(forceStopIntent)
            
            // 等待应用关闭
            delay(2000)
            
            // 重新启动应用
            val launchIntent = context.packageManager.getLaunchIntentForPackage(packageName)
            if (launchIntent != null) {
                launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                context.startActivity(launchIntent)
                delay(3000) // 等待应用启动
                return@withContext true
            }
            return@withContext false
        } catch (e: Exception) {
            Log.e(TAG, "Failed to restart app", e)
            return@withContext false
        }
    }
    
    /**
     * 打开应用设置
     */
    private fun openAppSettings(packageName: String) {
        try {
            val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
            intent.data = Uri.parse("package:$packageName")
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            context.startActivity(intent)
        } catch (e: Exception) {
            Log.e(TAG, "Failed to open app settings", e)
        }
    }
    
    /**
     * 找到应用入口步骤
     */
    private fun findAppEntryStep(plan: TaskExecutionPlan): String? {
        // 通常第一个启动应用的步骤为入口
        for (step in plan.steps) {
            if (step.actionType == ExecutionStep.ActionType.APP_LAUNCH) {
                return step.id
            }
        }
        return null
    }
    
    /**
     * 清除指定步骤的恢复尝试计数
     */
    fun clearRecoveryAttempts(stepId: String) {
        val keysToRemove = recoveryAttemptCounter.keys.filter { it.startsWith("$stepId:") }
        keysToRemove.forEach { recoveryAttemptCounter.remove(it) }
    }
    
    /**
     * 清除所有恢复尝试计数
     */
    fun clearAllRecoveryAttempts() {
        recoveryAttemptCounter.clear()
    }
} 